home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
nn.zip
/
RC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-31
|
14KB
|
641 lines
/*
* rc management routines
*/
#include "config.h"
#include "term.h"
#include "debug.h"
export int keep_rc_backup = 1;
export int no_update = 0;
export int use_newsrc = 0;
export long unread_articles; /* estimate of unread articles */
export int unread_groups;
static FILE *rc = NULL; /* rc_file descriptor */
static char RC[] = "rc";
static char BAK[] = "rc.bak";
static char NEWSRC[] = ".newsrc";
static int has_newsrc = 0;
/* RC lines have the format: */
/* SUBSCR space LASTART space GROUPNUM space NAME */
#define SUBSCRZ 1
#define SUBSCRPOS 0
#define SUBSCR(buf) buf[0]
/* NOTICE THAT LASTARTZ IS HARDCODED IN A printf FORMAT STRING LATER ON */
#define LASTARTZ 6
#define LASTARTPOS (SUBSCRPOS + SUBSCRZ + 1)
#define LASTART(buf) atol(buf + LASTARTPOS)
#define GROUPNAMEPOS (LASTARTPOS + LASTARTZ + 1)
#define GROUPNAME(buf) (buf + GROUPNAMEPOS)
#define NEW_OFFSET ((off_t)1) /* append to rc_file when written */
/*
* read rc file info to group headers
* master file has been read in
*/
#define G_OLD G_SELECTION
#define G_RENUM G_DONE
visit_rc_file()
{
FILE *bak, *newsrc;
register int c;
register group_header *gh;
register char *cp;
char line[512];
off_t rcpos; /* position in rc */
int warn_duplicates = 0, mk_bak, rd_newsrc, bak_used;
time_t m_rc, m_newsrc;
char rc_path[FILENAME], bak_path[FILENAME];
strcpy(rc_path, relative(nn_directory, RC));
strcpy(bak_path, relative(nn_directory, BAK));
rc = NULL; /* open rc-file */
rewind_rc(rc_path, OPEN_READ);
m_rc = 0;
if (rc != NULL) {
fseek(rc, (off_t)0, 2);
if (ftell(rc) > (off_t)0) {
fseek(rc, 0L, 0);
m_rc = m_time(rc);
}
}
rd_newsrc = use_newsrc;
m_newsrc = 0;
mk_bak = keep_rc_backup;
bak_used = 0;
if (m_rc == 0) { /* rc empty (i.e. new or corrupted) */
if ((bak = open_file(bak_path, OPEN_READ)) != NULL) {
m_rc = m_time(bak);
if (m_rc >= m_newsrc) {
printf("\nRestoring %s from %s\n", RC, BAK);
rewind_rc(rc_path, OPEN_CREATE | MUST_EXIST);
while ((c = getc(bak)) != EOF) putc(c, rc);
rewind_rc(rc_path, OPEN_READ | MUST_EXIST);
fclose(bak);
mk_bak = 0;
bak_used = 1;
}
} else {
rd_newsrc = 1;
display_help("welcome");
}
}
if (rd_newsrc) {
newsrc = open_file(relative(home_directory, NEWSRC), OPEN_READ);
if (newsrc != NULL) {
m_newsrc = m_time(newsrc);
has_newsrc = 1;
}
}
if (has_newsrc) {
if (m_rc < m_newsrc) {
if (bak_used) {
printf("\n%s is newer than %s -- use %s ? ",
NEWSRC, BAK, NEWSRC);
fl;
if (!yes(0)) m_newsrc = 0;
}
if (m_newsrc != 0) {
printf("\nReading from %s\n", NEWSRC);
if (m_rc != 0) {
fclose(rc);
rc = NULL;
unlink(bak_path);
if (link(rc_path, bak_path) < 0 || unlink(rc_path) < 0)
user_error("Cannot backup %s file\n", RC);
mk_bak = 0;
}
rewind_rc(rc_path, OPEN_CREATE | MUST_EXIST);
read_newsrc(newsrc);
rewind_rc(rc_path, OPEN_READ | MUST_EXIST);
}
}
fclose(newsrc);
}
if (rc == NULL) { /* no .nn/rc and no .newsrc */
bak = NULL;
goto endloop;
}
if (no_update) mk_bak = 0;
bak = mk_bak ? open_file(bak_path, OPEN_CREATE | MUST_EXIST) : NULL;
for(;;) {
rcpos = ftell(rc);
c = getc(rc);
cp = line;
while (c != NL) {
if (c == EOF) goto endloop;
*cp++ = c;
c = getc(rc);
}
*cp = NUL;
if (bak != NULL) {
fputs(line, bak);
fputc(NL, bak);
}
if (SUBSCR(line) != '+' && SUBSCR(line) != '!' && SUBSCR(line) != '=') {
/* unrecognized line */
continue;
}
if ((gh = lookup(GROUPNAME(line))) == NULL) continue;
if (gh->group_flag & G_OLD) {
printf("Duplicated entry in rc file: %s\n", gh->group_name);
warn_duplicates++;
}
gh->rc_offset = rcpos;
gh->group_flag |= G_OLD;
if (SUBSCR(line) == '+')
gh->group_flag |= G_SUBSCRIPTION;
if (SUBSCR(line) == '=')
gh->group_flag |= G_SUBSCRIPTION | G_NEW;
gh->last_article = LASTART(line);
if (gh->group_flag & (G_BLOCKED | G_NO_DIRECTORY)) {
/* We cannot trust this group, so we leave it alone */
/* group_menu after update_group will do what is necessary */
continue;
}
if (gh->last_article > gh->last_l_article)
gh->group_flag |= G_RENUM; /* mark for use below */
if (gh->first_l_article > gh->last_article ||
gh->last_article > gh->last_l_article)
gh->last_article = gh->first_l_article - 1;
if (gh->last_article < 0) gh->last_article = 0;
}
endloop:
if (warn_duplicates) {
printf("You can repair this using \"nntidy\"\n");
any_key(0);
}
rewind_rc(rc_path, OPEN_UPDATE | MUST_EXIST);
Loop_Groups_Header(gh) {
if (gh->group_flag & G_OLD) {
if (gh->group_flag & G_RENUM) /* group is renumbered */
write_rc_entry(gh, 0);
gh->group_flag &= ~(G_OLD | G_RENUM);
} else {
gh->group_flag |= G_SUBSCRIPTION | G_NEW;
gh->last_article = gh->first_l_article - 1;
if (gh->last_article < 0) gh->last_article = 0;
gh->rc_offset = NEW_OFFSET;
}
gh->first_article = gh->last_article;
}
if (bak != NULL) fclose(bak);
if (no_update) {
fclose(rc);
rc = NULL;
} else
fflush(rc);
}
rewind_rc(path, mode)
char *path;
{
if (rc != NULL) fclose(rc);
rc = open_file(path, mode);
}
restore_bak()
{
if (no_update)
return 1;
if (!keep_rc_backup) {
msg("No %s file ('backup' is not set)", BAK);
return 0;
}
prompt("Are you sure? ");
if (!yes(1)) return 0;
fclose(rc); /* cannot use close_rc() since it would update .newsrc */
rc = NULL;
if (chdir(nn_directory) < 0) goto err;
if (unlink(RC) < 0) goto err;
if (link(BAK, RC) < 0) goto err;
if (unlink(BAK) < 0) goto err;
return 1;
err:
clrdisp();
printf("Restore of %s file failed\n\n", RC);
printf("Check state of %s and %s files\n", RC, BAK);
nn_exit(1);
/*NOTREACHED*/
}
update_rc(gh)
register group_header *gh;
{
add_unread(gh, -1);
if (no_update || gh->group_flag & G_READ) return;
gh->last_article = gh->last_l_article;
#ifdef RC_TEST
if (Debug & RC_TEST)
fprintf(stderr, "upd_rc(%s) pos=%ld, artno=%ld\n",
gh->group_name, gh->rc_offset, gh->last_article);
#endif
write_rc_entry(gh, 0);
gh->group_flag |= G_READ;
}
restore_rc(gh, count)
register group_header *gh;
long count;
{
if (no_update || (count == 0 && (gh->group_flag & G_READ) == 0))
return 0;
if (gh->group_flag & G_READ || count > 0) {
add_unread(gh, -1);
if (count > 0) {
gh->last_article = gh->last_l_article - count;
if (gh->last_article < gh->first_l_article)
gh->last_article = gh->first_l_article - 1;
gh->first_article = gh->last_article;
} else
gh->last_article = gh->first_article;
#ifdef RC_TEST
if (Debug & RC_TEST)
fprintf(stderr, "restore_rc(%s) pos=%ld, artno=%ld\n",
gh->group_name, gh->rc_offset, gh->last_article);
#endif
write_rc_entry(gh, 0);
gh->group_flag &= ~G_READ;
add_unread(gh, 1);
return 1;
}
return 0;
}
close_rc()
{
off_t endrc;
if (rc == NULL) return;
if (use_newsrc) {
write_newsrc();
fflush(rc);
fseek(rc, 0L, 2); /* touch rc file */
if ((endrc = ftell(rc)) == 0)
fprintf(rc, "#\n");
else {
fflush(rc);
fseek(rc, endrc - 1, 0);
fputc(NL, rc);
}
}
fclose(rc);
rc = NULL;
}
count_unread_articles(trace)
int trace;
{
register group_header *gh;
long n;
unread_articles = 0;
unread_groups = 0;
Loop_Groups_Sequence(gh) {
gh->group_flag &= ~G_UNREAD_COUNT;
if ((gh->group_flag & G_SUBSCRIPTION) == 0) continue;
if (gh->group_flag & G_NO_DIRECTORY) continue;
if (gh->last_l_article > gh->last_article) {
n = unread_articles;
add_unread(gh, 1);
if (trace)
printf("%6d %s\n", unread_articles - n, gh->group_name);
}
}
}
prt_unread(format)
register char *format;
{
if (format == NULL) {
printf("No News (is good news)\n");
return;
}
while (*format) {
if (*format != '%') {
putchar(*format++);
continue;
}
format++;
switch (*format++) {
case 'u':
printf("%ld unread article%s",
unread_articles,
unread_articles == 1 ? "" : "s");
continue;
case 'g':
printf("%d group%s",
unread_groups,
unread_groups == 1 ? "" : "s");
continue;
case 'i':
printf(unread_articles == 1 ? "is" : "are");
continue;
case 'U':
printf("%ld", unread_articles);
continue;
case 'G':
printf("%d", unread_groups);
continue;
}
}
}
add_unread(gh, mode)
group_header *gh;
int mode; /* +1 => add, -1 => subtract */
{
long art;
int32 was_unread;
art = gh->last_l_article - gh->last_article;
was_unread = (gh->group_flag & G_UNREAD_COUNT);
if (mode > 0) {
if (was_unread) return 0;
unread_articles += art;
unread_groups++;
gh->group_flag |= G_UNREAD_COUNT;
} else {
if (!was_unread) return 0;
unread_articles -= art;
unread_groups--;
gh->group_flag &= ~G_UNREAD_COUNT;
}
return (was_unread != 0);
}
/*
* write one line on rc_file
*/
write_rc_entry(gh, new)
group_header *gh;
int new; /* 0 => old, 1 => quick append, 2 => normal append */
{
if (gh->rc_offset == NEW_OFFSET) new = 2;
if (new) {
if (new == 2) fseek(rc, (off_t)0, 2);
gh->rc_offset = ftell(rc);
} else
if (fseek(rc, gh->rc_offset, 0) < 0)
user_error("Seek error on %s file", RC);
/*
* the 'last article' is not updated in the rc file
* when a group is unsubscribed; if it is later resubscribed,
* the present articles will still be unread (if they exist)
*/
/* update article number */
fprintf(rc, "%c %06ld", /* MUST CHANGE IF LASTARTZ CHANGES */
(gh->group_flag & G_NEW) ? '=' :
(gh->group_flag & G_SUBSCRIPTION) ? '+' : '!',
(long)(gh->last_article));
if (new) {
fputc(' ', rc);
fputs(gh->group_name, rc);
fputc(NL, rc);
}
fflush(rc);
}
/*
* Old-style .newsrc support
*/
static read_newsrc(newsrc)
FILE *newsrc;
{
copy_newsrc(newsrc, (FILE *)NULL);
}
static write_newsrc()
{
char newsrc_path[FILENAME], bak_path[FILENAME];
FILE *newsrc, *bak;
strcpy(newsrc_path, relative(home_directory, NEWSRC));
sprintf(bak_path, "%s.bak", newsrc_path);
if (has_newsrc) {
unlink(bak_path);
if (link(newsrc_path, bak_path) < 0 || unlink(newsrc_path) < 0)
user_error("Cannot backup %s file\n", newsrc_path);
bak = open_file(bak_path, OPEN_READ | MUST_EXIST);
} else
bak = NULL;
if (file_exist(newsrc_path, (char *)NULL)) {
/* This is real paranoia ... don't let people lose their .newsrc */
/* This should not happen - but it has been seen */
log_entry('E', "failed to backup %s", newsrc_path);
fprintf(stderr, "PROBLEM... YOUR %s WAS NOT UPDATED\n", NEWSRC);
if (bak != NULL) fclose(bak);
return;
}
newsrc = open_file(newsrc_path, OPEN_CREATE | MUST_EXIST);
copy_newsrc(bak, newsrc);
if (bak != NULL) fclose(bak);
fclose(newsrc);
}
static copy_newsrc(old_rc, new_rc)
FILE *old_rc, *new_rc;
{
char buf[2048];
char *sub, *last, subscr;
long atol();
register group_header *gh;
Loop_Groups_Header(gh)
gh->group_flag &= ~G_DONE;
if (old_rc != NULL) {
/* NEWSRC lines have the following format */
/* NAME(n)SUBSCR(1) space NUM[,NUM][-NUM]... */
while (fgets(buf, 2048, old_rc) != NULL) {
subscr = 0;
if (sub = strchr(buf, ':'))
subscr = 1;
else
sub = strchr(buf, '!');
if (sub == NULL) {
if (new_rc != NULL) goto output_unchanged;
continue;
}
*sub = NUL;
gh = lookup(buf);
*sub++ = subscr ? ':' : '!';
if (gh == NULL) {
if (new_rc != NULL) goto output_unchanged;
continue;
}
if (new_rc != NULL) {
if (gh->group_flag & G_DONE) continue;
gh->group_flag |= G_DONE;
if (!subscr) goto output_unchanged;
write_newsrc_entry(new_rc, gh, (*sub == NL) ? 1 : 0);
continue;
}
/* Notice: unread articles before the last read article are lost */
if (subscr) {
if (*sub == NL) continue; /* new group */
last = strrchr(sub, '-');
if (last == NULL) last = strrchr(sub, ',');
if (last == NULL) last = strrchr(sub, ' ');
if (last == NULL) last = "0"; else last++;
gh->last_article = atol(last);
gh->group_flag |= G_SUBSCRIPTION;
} else
gh->last_article = 0;
gh->rc_offset = NEW_OFFSET;
write_rc_entry(gh, 0);
continue;
output_unchanged:
fputs(buf, new_rc);
}
}
Loop_Groups_Header(gh) {
if (new_rc != NULL) {
if (gh->group_flag & G_DONE) continue;
write_newsrc_entry(new_rc, gh, -1);
} else {
gh->rc_offset = 0;
gh->last_article = 0;
gh->group_flag &= G_MASTER_FLAGS;
}
}
return 1;
}
write_newsrc_entry(newsrc, gh, also_new)
FILE *newsrc;
register group_header *gh;
int also_new;
{
if ((gh->group_flag & G_READ) == 0 && (gh->group_flag & G_NEW)) {
if (also_new < 0) return;
} else
also_new = 0;
fprintf(newsrc, "%s%c", gh->group_name,
(gh->group_flag & G_SUBSCRIPTION) ? ':' : '!');
if (also_new) {
fputc(NL, newsrc);
return;
}
if (gh->first_l_article > gh->last_article)
fprintf(newsrc, " %s%d\n",
gh->first_l_article > 2 ? "1-" : "",
gh->first_l_article - 1);
else
fprintf(newsrc, " %d-%d\n", gh->first_l_article, gh->last_article);
}